home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / hard / hack / i2clib40.lha / i2clib40 / src / Play.c < prev    next >
C/C++ Source or Header  |  1998-08-22  |  4KB  |  158 lines

  1. /*========================================================================*
  2.  |  File: Play.c                                       Date: 22 Aug 1998  |
  3.  *------------------------------------------------------------------------*
  4.  |                Use the PCD3311/3312 to play melodies                   |
  5.  |                                                                        |
  6.  *========================================================================*/
  7.  
  8. #include <string.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <ctype.h>
  12. #include <time.h>
  13. #include <exec/types.h>
  14. #include <proto/exec.h>
  15. #include <proto/dos.h>
  16. #include <proto/i2c.h>
  17.  
  18. struct Library *I2C_Base;
  19.  
  20.  
  21. #define PCD3312 0x48    /* may be jumpered as 0x4A, too */
  22.  
  23. /* table: names of the notes and values to produce them */
  24. char caNotes[] = "DefFgGaAbcCdDefFgGaAbcCdD";
  25. BYTE baCodes[] = { 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
  26.                    0x38, 0x39, 0x3a, 0x29, 0x3b, 0x3c, 0x3d, 0x0e,
  27.                    0x3e, 0x2c, 0x3f, 0x04, 0x05, 0x25, 0x2f, 0x06,
  28.                    0x07 };
  29.  
  30.  
  31.  
  32.  
  33. void LibClose( struct Library **ppLib )
  34.     {
  35.     if( *ppLib )
  36.         {
  37.         CloseLibrary( *ppLib );
  38.         *ppLib = NULL;
  39.         }
  40.     }
  41.  
  42.  
  43.  
  44. struct Library* LibOpen( STRPTR strName, LONG lVersion )
  45.     {
  46.     struct Library* pLib;
  47.  
  48.     pLib = OpenLibrary( strName, lVersion );
  49.     if( !pLib )
  50.         {
  51.         printf( "Can't open %s", strName );
  52.         printf( lVersion ? " V%ld+\n" : "\n", lVersion );
  53.         exit( 10 );
  54.         }
  55.     else
  56.         return pLib;
  57.     }
  58.  
  59.  
  60.  
  61. void CleanUp()
  62.     {
  63.     SendI2C( PCD3312, 1, "\0" );
  64.     LibClose( &I2C_Base );
  65.     LibClose( (struct Library **)&DOSBase );
  66.     }
  67.  
  68.  
  69.     /* Takes a note name A through G and returns a code for it. */
  70.     /* If sharp != 0, assume it's raised by a halftone. */
  71.     /* If far == 0, return the code for the nearest note, else for */
  72.     /* the "other one". (We have two octaves available.) */
  73.     /* P means "pause" and returns the appropriate value of 0. */
  74.     /* H is accepted as an alias for B. */
  75.     /* All other values return 0x10, which is a dial tone. :-7 */
  76. int Translate( char c, int sharp, int far )
  77.     {
  78.     static int pos = 12;    /* start from the middle of the range */
  79.     int pos0, pos1;
  80.     char *s;
  81.     #define ABSDIFF( a, b ) ((a) > (b) ? (a)-(b) : (b)-(a))
  82.  
  83.     if( toupper( c ) == 'P' )
  84.         return 0;
  85.     if( toupper( c ) == 'H' )
  86.         c = 'B';
  87.     c = sharp ? toupper( c ) : tolower( c );
  88.     s = strchr( caNotes, c );
  89.     if( s == NULL )
  90.         return 0x10;
  91.     pos0 = s - caNotes;
  92.     pos1 = pos0 + 12;
  93.     /* Two possible choices. Which one is nearer? */
  94.     if( ABSDIFF( pos, pos0 ) < ABSDIFF( pos, pos1 ) )
  95.         pos = far ? pos1 : pos0;
  96.     else
  97.         pos = far ? pos0 : pos1;
  98.  
  99.     return baCodes[ pos ];
  100.     }
  101.  
  102.  
  103.  
  104. int main( int argc, char *argv[] )
  105.     {
  106.     int i;
  107.     int base = 8;              /* time base for playback */
  108.     long err;
  109.     char *s;
  110.     char c;
  111.  
  112.     if( argc < 2 )
  113.         {
  114.         printf( "Usage: \e[2m%s [timebase] <notes>\e[0m, ", argv[0] );
  115.         printf( "e.g. %s 16 f# d e Aa pp a E f# dd\n", argv[0] );
  116.         return 5;
  117.         }
  118.  
  119.     DOSBase  = NULL;
  120.     I2C_Base = NULL;
  121.     atexit( CleanUp );          /* close libraries upon Ctrl-C, too */
  122.     I2C_Base = LibOpen( "i2c.library", 39 );
  123.     DOSBase  = (struct DosLibrary *)LibOpen( "dos.library", 0 );
  124.  
  125.     i=1;
  126.     while( TRUE )
  127.         {
  128.         s = argv[ i ];
  129.         if( isdigit( *s ) )     /* read a new timebase */
  130.             {
  131.             base = atoi( s );
  132.             continue;
  133.             }
  134.         while( *s )             /* otherwise play notes (or pauses) */
  135.             {
  136.             c = Translate( *s, s[ 1 ] == '#', isupper( *s ) );
  137.             if( s[ 1 ] == '#' )
  138.                 s++;
  139.             err = SendI2C( PCD3312, 1, &c );
  140.             if( (err & 0xff)==0 )
  141.                 {
  142.                 printf("\nI²C failure: \e[1m%s\e[0m\n", I2CErrText(err) );
  143.                 exit( 10 );
  144.                 }
  145.             Delay( base );
  146.             s++;
  147.             if( !*s )
  148.                 SendI2C( PCD3312, 1, "\0" );
  149.             printf( "\r" );
  150.             fflush( stdout );   /* force GNU C to check for Ctrl-C :-( */
  151.             }
  152.         if( ++i == argc )
  153.             break;
  154.         }
  155.  
  156.     return 0;
  157.     }
  158.